<template>
<div>
    <!-- 面包屑导航区域 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>分类参数</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片区域 -->
    <el-Card>
      <!-- 渲染一个警告提示 -->
      <el-alert
      title="注意:只允许为第三级分类设置相关参数"
      type="warning"
      show-icon>
      </el-alert>
    <!-- 选择商品区域--级联选择器 -->
      <el-row class="cat_opt">
        <el-col :span="2.5" class="cat_opt_col">
        <span class="right">选择商品分类:</span>
        </el-col>
        <el-col :span="18">
          <!-- 级联选择器区域 -->
          <el-cascader
          expandTrigger:="hover"
          v-model="seletedKeys"
          :options="cateList"
          :props="CateProps"
          @change="selsetedChange"
          clearable>
          </el-cascader>
        </el-col>
      </el-row>
      <!-- tab栏区域 -->
      <el-tabs v-model="activeName" @tab-click="handleTabClick">
        <el-tab-pane label="动态参数" name="many">
          <el-button type="warning" size="mini" round :disabled="isDisabled"
          @click ="addParamsDialogVisible=true">添加参数</el-button>
          <!-- 渲染动态参数表格 -->
           <el-table
          :data="manyTableList"
          style="width: 100%"
          border stripe>
          <!-- 展开列 -->
          <el-table-column type="expand">
             <!-- 展开列会对应加载获取到的attr_vals -->
             <template slot-scope="scope">
             <el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable class="tag_opt" @close="TagClosed(i, scope.row)">{{ item }}</el-tag>
             <!-- 这是inputs输入框和button按钮交替实现的部分 -->
             <el-input
                class="input-new-tag"
                v-if="scope.row.inputVisible"
                v-model="scope.row.inputValue"
                ref="saveTagInput"
                size="small"
                @keyup.enter.native="handleInputConfirm(scope.row)"
                @blur="handleInputConfirm(scope.row)"
                >
            </el-input>
            <el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
            </template>
          </el-table-column>
          <!-- 索引列 -->
          <el-table-column type="index"></el-table-column>
          <el-table-column
            prop="attr_name"
            label="参数名称"
            width="360">
          </el-table-column>
          <el-table-column
            label="操作"
            width="360">
            <!-- slot-scope="scope" -->
            <template slot-scope="scope">
              <el-button type="danger"  class="el-icon-edit" round size="mini"  @click="editParams(scope.row.attr_id)">编辑</el-button>
              <el-button type="warning"  class="el-icon-delete" round size="mini" @click ="deleteParams(scope.row.attr_id)">删除</el-button>
            </template>
          </el-table-column>
          </el-table>
        </el-tab-pane>
        <el-tab-pane label="静态属性" name="only">
          <el-button type="warning" size="mini" round :disabled="isDisabled"
          @click ="addParamsDialogVisible=true">添加属性</el-button>
          <!-- 渲染静态参数属性 -->
          <el-table
          :data="onlyTableList"
          style="width: 100%"
          border stripe>
          <!-- 展开列 -->
         <el-table-column type="expand">
             <!-- 展开列会对应加载获取到的attr_vals -->
             <template slot-scope="scope">
             <el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable class="tag_opt" @close="TagClosed(i, scope.row)">{{ item }}</el-tag>
             <!-- 这是inputs输入框和button按钮交替实现的部分 -->
             <el-input
                class="input-new-tag"
                v-if="scope.row.inputVisible"
                v-model="scope.row.inputValue"
                ref="saveTagInput"
                size="small"
                @keyup.enter.native="handleInputConfirm(scope.row)"
                @blur="handleInputConfirm(scope.row)"
                >
            </el-input>
            <el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
            </template>
          </el-table-column>
          <!-- 索引列 -->
          <el-table-column type="index"></el-table-column>
          <el-table-column
            prop="attr_name"
            label="属性名称"
            width="360">
          </el-table-column>
          <el-table-column
            label="操作"
            width="360">
            <!-- slot-scope="scope" -->
            <template slot-scope="scope">
              <el-button type="danger"  class="el-icon-edit" round size="mini" @click="editParams(scope.row.attr_id)">编辑</el-button>
              <el-button type="warning"  class="el-icon-delete" round size="mini" @click ="deleteParams(scope.row.attr_id)">删除</el-button>
            </template>
          </el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-Card>
    <!-- 添加参数对话框 -->
    <!-- 因为添加参数有动态参数和静态属性两种，他们共用一个对话框 -->
    <el-dialog
      :title='"添加" + titleText'
      :visible.sync="addParamsDialogVisible"
      width="50%"
      @closed="addParamsDialogClosed">
      <el-form :model="addForm" :rules="addFormRules" ref="addFormRefs" label-width="100px" class="demo-ruleForm">
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="addForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addParamsDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addParams">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 修改参数对话框 -->
    <!-- 因为修改参数有动态参数和静态属性两种，他们共用一个对话框 -->
    <!-- 选中单词用ctrl+D可以选中相同的单词一起修改 -->
    <el-dialog
      :title='"修改" + titleText'
      :visible.sync="editParamsDialogVisible"
      width="50%"
      @closed="editParamsDialogClosed">
      <el-form :model="editForm" :rules="editFormRules" ref="editFormRefs" label-width="100px" class="demo-ruleForm">
        <el-form-item :label="titleText" prop="attr_name">
          <el-input v-model="editForm.attr_name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editParamsDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editParamsSubmit">确 定</el-button>
      </span>
    </el-dialog>
</div>
</template>

<script>
export default {
  data() {
    return {
      cateList: [],
      CateProps: {
        label: 'cat_name',
        value: 'cat_id',
        children: 'children'
      },
      seletedKeys: [],
      activeName: 'many',
      manyTableList: [],
      onlyTableList: [],
      addParamsDialogVisible: false,
      // 添加参数对话框的表单数据
      addForm: {
        attr_name: ''
      },
      // 添加参数对话框的验证规则
      addFormRules: {
        attr_name: [
          { required: true, message: '请输入动态参数名称', trigger: 'blur' },
          { min: 2, max: 9, message: '动态参数名称字符在2到9之间', trigger: 'blur' }
        ]
      },
      // 控制修改对话框的显示与隐藏
      editParamsDialogVisible: false,
      // 修改对话框绑定的数据源
      // 注意editForm里面保存的是某个数据，是对象
      editForm: {
        attr_name: ''
      },
      // 修改对话框对应的规则
      editFormRules: {
        attr_name: [
          { required: true, message: '该项是必填项', trigger: 'blur' },
          { min: 2, max: 9, message: '分类参数名称应该在2到9个字符之间', trigger: 'blur' }
        ]
      }
    }
  },
  created() {
    // 页面一家在就拿到商品分类数据
    this.getCateList()
  },
  // 注意这里的methods是复数，必须是复数，否则报错
  methods: {
    // 请求商品分类所有的数据（一级，二级，三级）
    async getCateList() {
      const { data: res } = await this.$http.get('categories')
      if (res.meta.status !== 200) {
        return this.$message.error('商品分类数据获取失败')
      }
      console.log(res)
      this.cateList = res.data
      console.log('商品分类获取成功')
    },
    // 级联选择框选中的keys改变触发的事件
    async selsetedChange() {
      this.getActionCate()
    },
    handleTabClick() {
      this.getActionCate()
    },
    async getActionCate() {
      // 判断选中的是不是三级分类
      if (this.seletedKeys.length !== 3) {
        this.seletedKeys = []
        this.manyTableList = []
        this.onlyTableList = []
        return
      }
      // 选中了三级分类，可以对应加载相关参数
      // console.log(this.selectedKeys)
      // 发送请求获取当前选中的三级分类的相关参数
      // sel是一个get参数，但是不携带在url中，通过params指定
      const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`,
        {
          params: { sel: this.activeName }
        })
      if (res.meta.status !== 200) {
        return this.$message.error('该商品的分类参数获取失败')
        // 根据代码规范，else语句应该接在}之后，否则报格式不规范
      } else {
        // 获取的三级分类参数里面attr_vals这一项需要更改成数组形式
        // 注意：此处应该先对attr_vals做一下判断，若是attr_vals不为空，才进行分割
        // 若是attr_vals为空，那么''.split(',')会返回一个数组里面有一项空值，会涌现el-tag标签的渲染
        res.data.forEach(item => {
          item.attr_vals = item.attr_vals ? item.attr_vals.split(',') : []
          // 为了保证每一向参数的input输入框和button按钮切换绑定值的唯一性
          item.inputVisible = false
          item.inputValue = ''
        })
        console.log(res)
        console.log('该商品的分类参数获取成功')
        // 根据activeName是谁，来把数据分类是动态参数的数据还是静态数据的参数
        if (this.activeName === 'many') {
          this.manyTableList = res.data
        } else {
          this.onlyTableList = res.data
        }
      }
    },
    // 控制添加参数对话框关闭后进行清空
    addParamsDialogClosed() {
      this.$refs.addFormRefs.resetFields()
    },
    // 点击提娜佳对话框的确定按钮之后触发
    addParams() {
      // 继续宁表单预校验
      this.$refs.addFormRefs.validate(async valid => {
        // !valid的意思是！false是通过的，也就是！valid = true，则自身valid必然为false,则校验不通过
        if (!valid) return
        // 发送请求
        const { data: res } = await this.$http.post(`categories/${this.cateId}/attributes`, {
          attr_name: this.addForm.attr_name,
          attr_sel: this.activeName
        })
        // console.log(res)
        // 判断状态码
        if (res.meta.status !== 201) {
          return this.$message.error('添加参数失败')
        }
        // 刷新一下参数表格
        this.getActionCate()
        // 关闭对话框
        this.addParamsDialogVisible = false
        // 弹出消息
        this.$message.success('分类参数添加成功')
      })
    },
    // 修改对话框关闭后的重置事件
    // 注意是重置事件，不是清空事件，重置回到原来的样子
    editParamsDialogClosed() {
      this.$refs.editFormRefs.resetFields()
    },
    // 点击修改编辑按钮事件
    async editParams(pid) {
      // 点击了修改按钮，首先应该向后端请i去该分类的具体信息
      const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes/${pid}`, {
        params: { attr_sel: this.activeName }
      })
      // console.log(pid)
      console.log(res)
      if (res.meta.status !== 200) {
        this.$message.error('该分类参数获取失败')
      }
      // 将分类参数的具体信息保存到editForm中，方便修改
      this.editForm = res.data
      // 将对话框打开
      this.editParamsDialogVisible = true
    },
    // 点击对话框修改按钮提交事件
    editParamsSubmit() {
      // 点击确定按钮之后，因嘎嘎i先对表单进行预校验
      this.$refs.editFormRefs.validate(async valid => {
        if (!valid) return
        // 发送请求到后台更新数据
        const { data: res } = await this.$http.put(`categories/${this.cateId}/attributes/${this.editForm.attr_id}`, {
          // 函数的请求体部分
          attr_name: this.editForm.attr_name,
          attr_sel: this.activeName
        })
        // console.log(res)
        if (res.meta.status !== 200) {
          this.$message.error('更新该分类的名字失败')
        }
        // 刷新一下分类列表
        this.getActionCate()
        // 关闭对话框
        this.editParamsDialogVisible = false
      })
    },
    // 删除参数
    async deleteParams(pid) {
      // 点击删除按钮触发一个messageBox，提示是否真的要删除
      // 当用户在messageBox里面选用的是cancel,将会弹出错误，catch是用来捕获这个错误并且将错误抛出
      const confirmResult = await this.$confirm('此操作将永久删除该参数, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(err => err)
      // console.log(confirmResult)
      // 点击确定返回confirm，点击取消返回cancel
      if (confirmResult === 'cancel') {
        this.$message.Info('已经取消删除')
      }
      // 向后端发送请求删除数据
      const { data: res } = await this.$http.delete(`categories/${this.cateId}/attributes/${pid}`)
      // console.log(res)
      if (res.meta.status !== 200) {
        this.$message.error('删除该分类参数失败')
      }
      // 刷新数据列表
      this.getActionCate()
      // 弹出消息
      this.$message.success('删除该分类参数成功')
    },
    // input输入框和Button按钮交替显示的事件
    handleInputConfirm(scopeRow) {
      // console.log('ok')
      // 失去焦点或者键入enter会触发
      // 判断用户是否输入了有效的内容
      if (scopeRow.inputValue.trim().length === 0) {
        scopeRow.inputValue = ''
        // 将input输入框再转变回来button
        scopeRow.inputVisible = false
        return
      }
      // 程序到这说明用户输入了有效的值
      // 将用户新输入的值push到attr-vals数组当中
      scopeRow.attr_vals.push(scopeRow.inputValue)
      // 将inputvalue进行置空
      scopeRow.inputValue = ''
      // 将input输入框再转变回来button
      scopeRow.inputVisible = false
      // 调用函数对后端发送请求更新参数列表
      this.editCateAndSubmit(scopeRow)
    },
    // 编辑提交分类参数的函数
    async editCateAndSubmit(scopeRow) {
      // 向后端接口提交新的分类参数
      const { data: res } = await this.$http.put(`categories/${this.cateId}/attributes/${scopeRow.attr_id}`, {
        attr_name: scopeRow.attr_name,
        attr_sel: scopeRow.attr_sel,
        attr_vals: scopeRow.attr_vals.join(',')
      })
      // console.log(res)
      if (res.meta.status !== 200) {
        this.$message.error('更新参数失败')
      }
      this.$message.success('更新参数成功')
    },
    // 点击button转换成input输入框的事件
    showInput(scopeRow) {
      scopeRow.inputVisible = true
      // 注释一下：$nextTick事件是当页面的元素重新渲染以后会触发的事件
      // 当点击完成Button之后，需要经过一点时间才能变成input,也就是要当input渲染完成以后再调用下面给
      // input获取焦点的方法，$nextTick事件可以做到
      // 要是不等页面重新渲染完成就调用，找不到input-------报错
      this.$nextTick(_ => {
        // 将焦点定位在input输入框
        this.$refs.saveTagInput.$refs.input.focus()
      })
    },
    // 点击tag标签上的x号出发的删除标签事件
    TagClosed(i, scopeRow) {
      scopeRow.attr_vals.splice(i, 1)
      // 对attr_vals进行了删除以后，需要再向服务器提交新的attr_vals给刷新
      this.editCateAndSubmit(scopeRow)
    }
  },
  computed: {
    // 定义一个计算属性，来控制按钮添加分类和添加属性按钮是否可以使用
    isDisabled() {
      // 选中的不是三级属性
      console.log(this.seletedKeys.length)
      if (this.seletedKeys.length !== 3) {
        return true
      }
      return false
    },
    // 定义一个计算属性是三级分类id
    cateId() {
      if (this.seletedKeys.length === 3) {
        return this.seletedKeys[2]
      }
      return null
    },
    // 定义一个计算属性，来控制添加参数对话框的名字
    titleText() {
      // 根据大哥前选中的选项卡是动态参数还是静态属性，来决定dialog的title值
      if (this.activeName === 'many') {
        return '动态参数'
      }
      return '静态属性'
    }
  }
}
</script>

<style lang="less" scoped>
.cat_opt {
  margin: 15px
}
.cat_opt_col {
  line-height: 40px;
}
.right {
  margin-right: 10px;
}
.tag_opt {
  margin: 10px;
}
.input-new-tag {
  width: 100px;
  margin: 10px;
}
.button-new-tag {
  margin: 10px;
}
</style>
